package com.lzw.breezeNovel.webApp.message;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lzw.breezeNovel.common.utils.ChannelContentUtils;
import com.lzw.breezeNovel.common.utils.JwtUtil;
import com.lzw.breezeNovel.model.entity.pojo.user.UserInfo;
import com.lzw.breezeNovel.webApp.mapper.user.UserInfoMapper;
import com.lzw.breezeNovel.webApp.service.message.MessageService;
import com.lzw.breezeNovel.webApp.vo.message.MessageVO;
import io.jsonwebtoken.Claims;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * @author 清风明月
 * @Package com.lzw.breezeNovel.webApp.message
 * @date 2025/3/27
 * @description 自定义webScoket处理消息
 */
@Slf4j
@Component
@ChannelHandler.Sharable
@SuppressWarnings("all")
public class HandelWebSocket  extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    /**
     * 消息类型
     */
    private static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 注入service
     */
    @Autowired
    private MessageService messageService;
    /**
     * 注入service
     */
    @Autowired
    private UserInfoMapper userInfoMapper;

    private Map<String, List<byte[]>> chunkBuffers = new ConcurrentHashMap<>();

    /**
     * 连接成功
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("连接成功");
    }

    /**
     * 断开连接
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
      log.info("断开连接");
    }

    /**
     * 读取数据
     * @param channelHandlerContext
     * @param textWebSocketFrame
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) {
        try {
            //获取消息内容
            String message = msg.text();
            System.out.println("收到消息" + message);
            //解析消息
            Map<String, Object> map = objectMapper.readValue(message, Map.class);
            //获取消息类型
            int type = (int) map.get("type");
            //获取发送者id
            int from = (int) map.get("from");
            //获取接收者id
             int to = (int) map.get("to");
             //获取内容
             String content = (String) map.get("content");
            //处理消息
            handleMessage(ctx, Long.valueOf(from), Long.valueOf(to), content, type);
        } catch (Exception e)
        {
            log.error("解析消息失败", e);
        }
    }

    /**
     * 处理消息
     * @param ctx
     * @param from
     * @param to
     * @param content
     * @param type
     */
    private void handleMessage(ChannelHandlerContext ctx, Long from, Long to, String content, int type) throws JsonProcessingException {
        //添加消息到数据库
        messageService.addMessage(to, from, content, type);
        //构建id获取消息的发送者
        UserInfo sender = userInfoMapper.selectById(from);
        //根据id获取手机号
        UserInfo userInfo = userInfoMapper.selectById(to);
        //创建消息对象
        MessageVO message = new MessageVO();
        message.setSenderId(from);
        message.setReceiverId(to);
        message.setContent(content);
        message.setType(type);
        message.setSendUser(sender);
        //把他转成json
        String json = objectMapper.writeValueAsString(message);
        // 获取接收者的channel
        Channel receiverChannel = ChannelContentUtils.getChannelByPhone(userInfo.getPhone());
        if (receiverChannel != null) {
            // 发送消息
            receiverChannel.writeAndFlush(new TextWebSocketFrame(json));
        }
    }

    /**
     * 用户事件触发
     * @param ctx
     * @param evt
     * @throws Exception
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
            // 握手成功
            WebSocketServerProtocolHandler.HandshakeComplete handshakeComplete = (WebSocketServerProtocolHandler.HandshakeComplete) evt;
            String requestUri = handshakeComplete.requestUri();
            // 提取access-token
            String accessToken = extractAccessToken(requestUri);
            if (accessToken == null || accessToken.isEmpty()) {
                log.info("认证失败: access-token为空");
                ctx.close();
                return;
            }

            // 验证access-token
            if (!validateToken(accessToken, ctx)) {
                log.info("认证失败: access-token无效");
                ctx.close();
                return;
            }
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }


    /**
     * 心跳检测
     * @param requestUri
     * @return
     */
    @Nullable
    private String extractAccessToken(String requestUri) {
        try {
            URI uri = new URI(requestUri);
            String query = uri.getQuery();
            if (query != null) {
                String[] params = query.split("&");
                for (String param : params) {
                    String[] keyValue = param.split("=");
                    if (keyValue.length == 2 && "access-token".equals(keyValue[0])) {
                        return keyValue[1];
                    }
                }
            }
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 验证token
     * @param token
     * @return
     */
    private boolean validateToken(@NotNull String token, @NotNull ChannelHandlerContext ctx) {
        // 这里实现你的token验证逻辑
        if (token.split("\\.").length != 3) {
            return false;
        }
        try{
            Claims claims = JwtUtil.parseToken(token);
            //获取用户手机号
            String phone = (String) claims.get("phone");
            //将用户手机号存入channel中
            Channel channel = ctx.channel();
            ChannelContentUtils.setChannelContent(phone,channel);
            return true;
        }catch (Exception e)
        {
            return false;
        }
    }
}
